package common.intercepter.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import common.beans.PermissionDto;
import common.beans.User;
import common.beans.UserResCommon;
import common.config.AppConfig;
import common.encryption.XXTEA;
import common.intercepter.entity.UimsResources;
import common.intercepter.entity.UimsUser;
import common.intercepter.http.RestTemplate;
import common.util.CacheUtil;
import common.util.RSAUtils;
import common.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class
TokenAuthorizingService {

    @Resource
    HttpSession session;

    @Resource
    CacheUtil cacheUtil;

    @Resource
    HttpServletRequest request;

    @Resource
    HttpServletResponse response;


    public boolean verifyJwt(String token) {
        JWTVerifier verifier = JWT.require(Algorithm.RSA256(RSAUtils.getRSAPublidKeyBybase64(AppConfig.RSA_PUBLIC_KEY), null)).build();
        try {
            verifier.verify(token);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("token非法!!");
            return false;
        }
        return true;
    }

    public boolean doGetAuthenticationInfo(String sessionId) throws Exception {
        String xxteaToken = "";
        Long time = System.currentTimeMillis();
        String md5Key = SecureUtil.md5(AppConfig.SSO_SKEY + time);
        xxteaToken = XXTEA.encryptToBase64String(sessionId, md5Key);
        String result = RestTemplate.requestUserInfo(xxteaToken, time);
        log.debug("Token获取的用户信息--" + result);
        JSONObject jsonObject = JSONUtil.parseObj(result);
        if (jsonObject.getInt("code").equals(0)) {
            User user = parseUserInfo(jsonObject);
            UserUtil.setAccessId(user.getUid() + "");
            // 添加我的权限信息
            log.info("开始从我的中心获取权限token");
            log.info("开始从我的中心获取权限___AppConfig.APP_ID" + AppConfig.APP_ID);
            Long time2 = System.currentTimeMillis();
            String md5Keyqfxc = SecureUtil.md5(AppConfig.SSO_SKEYOTHER + time2);
            String xxteaTokenqfxc = XXTEA.encryptToBase64String(user.getUid() + "", md5Keyqfxc);
            String qfxcPerAll = RestTemplate.requestQFXCUserAllPermissions(user.getUid(), time2, xxteaTokenqfxc);

            JSONObject objQFXC = JSONUtil.parseObj(qfxcPerAll);
            if (objQFXC.getInt("code").equals(0)) {
                String objStrqfxc = objQFXC.getStr("data");
                boolean b = parseUserPermissionsQFXC(objStrqfxc, user);
                cacheUtil.saveObject("user", user);
                return b;
            }
        } else {
            //因为cookie失效,本地方需要清空用户标志.
            log.info("接口认证失败!!");
            UserUtil.setAccessId("");
            expireCookie("tsguser");
        }
        return false;
    }

    public boolean doGetAuthorizationInfo(User user) {
        try {
            if (user.getAppResMap() == null) {
                user.setAppResMap(new HashMap<>());
            }

            // 2024年5月24日11:28:27 这里因为是别的yuntsg项目如果进来了 会冲掉存在user的 AppResMapQFXC 属性 如果冲掉了 直接重新获取赋值保存
            dealAppResMapQFXC(user);

            try {
                if (ObjectUtil.isNotNull(user.getAppResMapQFXC().get(Long.valueOf(AppConfig.APP_ID + "")))) {
//                UserResCommon userResCommon = user.getAppResMapQFXC().get(AppConfig.APP_ID);
//                parseUserPermissions(objStr, user);
//                cacheUtil.saveObject("user", user);
                    return true;
                }
            }catch (Exception e){
                
            }


            //将获取到的权限存入user中
            String xxteaToken = "";
            Long time = System.currentTimeMillis();
            String md5Key = SecureUtil.md5(AppConfig.SSO_SKEY + time);
            xxteaToken = XXTEA.encryptToBase64String(user.getUid() + "", md5Key);
            String permissionStr = RestTemplate.requestUserPermissions(xxteaToken, time);
            JSONObject obj = JSONUtil.parseObj(permissionStr);
            if (obj.getInt("code").equals(0)) {
                String objStr = obj.getStr("data");
                if (!objStr.equals("[]")) {
                    user.getAppResMap().put(AppConfig.APP_ID, objStr);
                    parseUserPermissions(objStr, user);
                    cacheUtil.saveObject("user", user);
                    return true;
                } else {
                    // 2024年2月22日16:41:18 添加从我的中心那里获取权限.
                    // 2024年4月19日10:12:11 现在不需要子系统获取权限,直接学习中心就获取全部权限存储在token 通过解析存储了 下面不需要了
                    Long time2 = System.currentTimeMillis();
                    String md5Keyqfxc = SecureUtil.md5(AppConfig.SSO_SKEYOTHER + time2);
                    String xxteaTokenqfxc = XXTEA.encryptToBase64String(user.getUid() + "", md5Keyqfxc);
                    log.info("开始从我的中心获取权限___AppConfig.APP_ID" + AppConfig.APP_ID);
                    String qfxcPerAll = RestTemplate.requestQFXCUserAllPermissions(user.getUid(), time2, xxteaTokenqfxc);
                    JSONObject objQFXC = JSONUtil.parseObj(qfxcPerAll);
                    if (objQFXC.getInt("code").equals(0)) {
                        String objStrqfxc = objQFXC.getStr("data");
                        boolean b = parseUserPermissionsQFXC(objStrqfxc, user);
                        cacheUtil.saveObject("user", user);
                        return b;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }

    public void dealAppResMapQFXC(User user) {
        if (user.getAppResMapQFXC() == null) {
            log.info("别的yuntsg 项目冲掉了AppResMapQFXC  重新赋值保存 ");
            Long time2 = System.currentTimeMillis();
            String md5Keyqfxc = SecureUtil.md5(AppConfig.SSO_SKEYOTHER + time2);
            String xxteaTokenqfxc = XXTEA.encryptToBase64String(user.getUid() + "", md5Keyqfxc);
            String qfxcPerAll = RestTemplate.requestQFXCUserAllPermissions(user.getUid(), time2, xxteaTokenqfxc);
            JSONObject objQFXC = JSONUtil.parseObj(qfxcPerAll);
            if (objQFXC.getInt("code").equals(0)) {
                String objStrqfxc = objQFXC.getStr("data");
                boolean b = parseUserPermissionsQFXC(objStrqfxc, user);
                cacheUtil.saveObject("user", user);

            }
        }
    }

    public boolean decryptToken(String jwtToken) throws Exception {

        if (!verifyJwt(jwtToken)) {
            return false;
        }
        Long userId = JWT.decode(jwtToken).getClaim("userid").asLong();
        if (userId == null) {
            return false;
        }
        UserUtil.setAccessId(userId + "");
        if (cacheUtil.existsKey("user")) {
            User user = (User) cacheUtil.getObject("user");
            //  打印下用户信息
            log.info("printUserInfo+");
            printUserInfo(user);
            log.info("cacheUtil存在Token");
            return true;
        }
        String sessionId = "";
        Claim appsession = JWT.decode(jwtToken).getClaim("appsessionid");
        Claim mobsessionid = JWT.decode(jwtToken).getClaim("mobsessionid");
        Claim pcsessionid = JWT.decode(jwtToken).getClaim("pcsessionid");
        if (appsession != null && appsession.asString() != null) {
            sessionId = appsession.asString();
        } else if (mobsessionid != null && mobsessionid.asString() != null) {
            sessionId = mobsessionid.asString();
        } else if (pcsessionid != null && pcsessionid.asString() != null) {
            sessionId = pcsessionid.asString();
        }
        log.debug("Token解密的Sessionid:" + sessionId);
        return doGetAuthenticationInfo(sessionId);
    }

    public static void printUserInfo(User user) {
        Map<Long, UserResCommon> appResMapQFXC = user.getAppResMapQFXC();
//        log.info("appResMapQFXC+" + appResMapQFXC);
        if (appResMapQFXC == null) {
            log.info("appResMapQFXC为空");
            return;
        }
        Set<Long> longs = appResMapQFXC.keySet();
        System.out.println(longs);
        Long aLong = Long.valueOf(AppConfig.APP_ID + "");
        log.info("along+" + aLong);
        if (appResMapQFXC != null) {
            boolean b = appResMapQFXC.containsKey(aLong);
            log.info("b+" + b);
            if (b) {
                UserResCommon userResCommon = appResMapQFXC.get(aLong);
                log.info("userInfo+" + (userResCommon));
            } else {
                log.info("不存在appconfiog+id+" + AppConfig.APP_ID);

            }
        }
    }

    private User parseUserInfo(JSONObject jsonObject) {
        User user = new User();
        String data = jsonObject.getStr("data");
        UimsUser uimsResUser = JSONUtil.parseObj(data).toBean(UimsUser.class);
        log.info("获取的数据信息" + uimsResUser);
        user.setUid(Integer.parseInt(String.valueOf(uimsResUser.getId())));
        user.setGid(Integer.parseInt(String.valueOf(uimsResUser.getInsId())));
        user.setPhone(uimsResUser.getMobile());
        user.setUnitName(uimsResUser.getUimsInstitution().getInsName());
        user.setIdentificationType(1);
        user.setInProbation(uimsResUser.getInProbation());
        user.setUnitEndDate(uimsResUser.getUnitEndDate());
        BeanUtils.copyProperties(uimsResUser, user);
        log.info("存储的用户信息:" + user.toString());
        return user;
    }


    private void parseUserPermissions(String objStr, User user) {
        List<UimsResources> resList = JSONUtil.toList(JSONUtil.parseArray(objStr), UimsResources.class);
//        log.info("权限集合: " + resList.toString());
        Map<Long, Integer> resMap = resList.stream().collect(Collectors.toMap(UimsResources::getId, UimsResources::getResValue));
        List<PermissionDto> permissionList = new ArrayList<>();
        if (resMap.containsKey(AppConfig.APP_ID)) {
            //开关型是名字加null  数值就是名字加数值
            PermissionDto permissionDto = new PermissionDto("学术助手", null);
            permissionList.add(permissionDto);
        }
        user.setPermissionList(permissionList);
    }

    //获取全部权限 并且判断当前项目权限并且存储在当前用户权限列表中
    public static boolean parseUserPermissionsQFXC(String objStr, User user) {
        List<UserResCommon> resList = JSONUtil.toList(JSONUtil.parseArray(objStr), UserResCommon.class);
        boolean isAccess = false;
        Long current = System.currentTimeMillis();
        Map<Long, UserResCommon> appResMapQFXC = user.getAppResMapQFXC();
//        Map<String, Boolean> AppResRekeyPMapQFXC = user.getAppResRekeyPMapQFXC();
        if (appResMapQFXC == null) {
            Map<Long, UserResCommon> AppResMapQFXC = new HashMap<>();
            user.setAppResMapQFXC(AppResMapQFXC);
            appResMapQFXC = user.getAppResMapQFXC();
        }
//        if (AppResRekeyPMapQFXC == null) {
//            Map<String, Boolean> APPResRekeyPMapQFXC = new HashMap<>();
//            user.setAppResRekeyPMapQFXC(APPResRekeyPMapQFXC);
//            AppResRekeyPMapQFXC = user.getAppResRekeyPMapQFXC();
//        }
        List<PermissionDto> permissionList = new ArrayList<>();

        for (UserResCommon userRes : resList) {
            if (userRes.getResId().intValue() == AppConfig.APP_ID && userRes.getAccess()) {
                isAccess = true;
            }
            if (userRes.getResId().intValue() == 10203) {
                //有申请全文权限
                PermissionDto permissionDto = new PermissionDto("QW", null);
                permissionList.add(permissionDto);
            }
            appResMapQFXC.put(userRes.getResId(), userRes);
//            AppResRekeyPMapQFXC.put(userRes.getReKey(), userRes.getAccess());
        }


        user.setPermissionList(permissionList);
        user.setAppResMapQFXC(appResMapQFXC);
//        user.setAppResRekeyPMapQFXC(AppResRekeyPMapQFXC);
        return isAccess;
    }

    public void expireCookie(String name) {
        Cookie cookies = new Cookie(name, null);
        cookies.setPath("/");
        cookies.setDomain(AppConfig.COOKIE_DOMAIN);
        cookies.setMaxAge(0);
        response.addCookie(cookies);
    }

}
